<!doctype html>
<html lang="en">
  <head>
    <!--
    noVNC example: lightweight example using minimal UI and features

    This is a self-contained file which doesn't import WebUtil or external CSS.

    Copyright (C) 2019 The noVNC Authors
    noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
    This file is licensed under the 2-Clause BSD license (see LICENSE.txt).

    Connect parameters are provided in query string:
        http://example.com/?host=HOST&port=PORT&scale=true
    -->
    <title>noVNC</title>

    <meta charset="utf-8" />

    <style>
      body {
        margin: 0;
        background-color: dimgrey;
        height: 100%;
        display: flex;
        flex-direction: column;
      }
      html {
        height: 100%;
      }

      #top_bar {
        display: none;
        background-color: #6e84a3;
        color: white;
        font: bold 12px Helvetica;
        padding: 6px 5px 4px 5px;
        border-bottom: 1px outset;
      }
      #status {
        text-align: center;
      }
      #sendCtrlAltDelButton {
        display: none;
        position: fixed;
        top: 0px;
        right: 0px;
        border: 1px outset;
        padding: 5px 5px 4px 5px;
        cursor: pointer;
      }

      #screen {
        flex: 1; /* fill remaining space */
        overflow: hidden;
      }
    </style>

    <script type="module" crossorigin="anonymous">
      // RFB holds the API to connect and communicate with a VNC server
      import RFB from "./core/rfb.js";

      let rfb;
      let desktopName;

      // When this function is called we have
      // successfully connected to a server
      function connectedToServer(e) {
        status("Connected to " + desktopName);
      }

      // This function is called when we are disconnected
      function disconnectedFromServer(e) {
        if (e.detail.clean) {
          status("Disconnected, retrying...");
          setTimeout(connect, 2000);
        } else {
          status("Something went wrong, connection is closed");
        }
      }

      // When this function is called, the server requires
      // credentials to authenticate
      function credentialsAreRequired(e) {
        const password = prompt("Password Required:");
        rfb.sendCredentials({ password: password });
      }

      // When this function is called we have received
      // a desktop name from the server
      function updateDesktopName(e) {
        desktopName = e.detail.name;
      }

      // Since most operating systems will catch Ctrl+Alt+Del
      // before they get a chance to be intercepted by the browser,
      // we provide a way to emulate this key sequence.
      function sendCtrlAltDel() {
        rfb.sendCtrlAltDel();
        return false;
      }

      // Show a status text in the top bar
      function status(text) {
        document.getElementById("status").textContent = text;
      }

      // This function extracts the value of one variable from the
      // query string. If the variable isn't defined in the URL
      // it returns the default value instead.
      function readQueryVariable(name, defaultValue) {
        // A URL with a query parameter can look like this (But will most probably get logged on the http server):
        // https://www.example.com?myqueryparam=myvalue
        //
        // For privacy (Using a hastag #, the parameters will not be sent to the server)
        // the url can be requested in the following way:
        // https://www.example.com#myqueryparam=myvalue&password=secreatvalue
        //
        // Even Mixing public and non public parameters will work:
        // https://www.example.com?nonsecretparam=example.com#password=secreatvalue
        //
        // Note that we use location.href instead of location.search
        // because Firefox < 53 has a bug w.r.t location.search
        const re = new RegExp(".*[?&]" + name + "=([^&#]*)"),
          match = ""
            .concat(document.location.href, window.location.hash)
            .match(re);

        if (match) {
          // We have to decode the URL since want the cleartext value
          return decodeURIComponent(match[1]);
        }

        return defaultValue;
      }

      document.getElementById("sendCtrlAltDelButton").onclick = sendCtrlAltDel;

      // Read parameters specified in the URL query string
      // By default, use the host and port of server that served this file
      const host = readQueryVariable("host", window.location.hostname);
      let port = readQueryVariable("port", window.location.port);
      const password = readQueryVariable("password");
      const path = readQueryVariable("path", "websockify");

      // | | |         | | |
      // | | | Connect | | |
      // v v v         v v v
      function connect() {
        status("Connecting");

        // Build the websocket URL used to connect
        let url;
        if (window.location.protocol === "https:") {
          url = "wss";
        } else {
          url = "ws";
        }
        url += "://" + host;
        if (port) {
          url += ":" + port;
        }
        url += "/" + path;

        // Creating a new RFB object will start a new connection
        rfb = new RFB(document.getElementById("screen"), url, {
          credentials: { password: password },
        });

        // Add listeners to important events from the RFB module
        rfb.addEventListener("connect", connectedToServer);
        rfb.addEventListener("disconnect", disconnectedFromServer);
        rfb.addEventListener("credentialsrequired", credentialsAreRequired);
        rfb.addEventListener("desktopname", updateDesktopName);

        // Set parameters that can be changed on an active connection
        rfb.viewOnly = readQueryVariable("view_only", false);
        rfb.scaleViewport = readQueryVariable("scale", false);
      }

      connect();
    </script>
  </head>

  <body>
    <div id="top_bar">
      <div id="status">Loading</div>
      <div id="sendCtrlAltDelButton">Send CtrlAltDel</div>
    </div>
    <div id="screen">
      <!-- This is where the remote screen will appear -->
    </div>
  </body>
</html>
